﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace System
{
    /// <summary>
    /// 二进制数据 操作,对单个数组替换时,如果新值长度小于旧值长度时出现的问题进行了修改
    /// </summary>
    public static class HexUtility
    {
        /// <summary>
        /// 二进制替换,如果没有替换则返回原数组对像的复本.比使用List效率高25%
        /// </summary>
        /// <param name="sourceByteArray">源数据</param>
        /// <param name="oldValue">需要替换的数据</param>
        /// <param name="newValue">将要替换成为的数据</param>
        public static byte[] Replace(this byte[] sourceByteArray, byte[] oldValue, byte[] newValue)
        {
            //创建新数据多出1字节
            int newArrayLen = (int)((newValue.Length / (double)oldValue.Length) * sourceByteArray.Length) + 1;
            //得到数组长度
            newArrayLen = Math.Max(newArrayLen, sourceByteArray.Length);
            //新的最后结果数组
            byte[] newByteArray = new byte[newArrayLen];
            //新数组的当前索引
            int curIndex = 0;
            //开始结束
            int start = -1;
            int end = -1;
            //当前查找到的索引
            int oldCurindex = 0;
            //替换数据替换
            for (int x = 0; x < sourceByteArray.Length; x++)
            {
                newByteArray[curIndex] = sourceByteArray[x];
                curIndex++;
                //查找要替换的数据
                if (sourceByteArray[x] == oldValue[oldCurindex])
                {
                    if (oldCurindex == 0)
                    {
                        start = x;
                    }
                    if (oldCurindex == oldValue.Length - 1)
                    {
                        end = x;
                        oldCurindex = 0;
                    }
                    else
                    {
                        oldCurindex++;
                    }
                }
                else
                {
                    oldCurindex = 0;
                }
                //数据查找完成
                if (start != -1 && end != -1)
                {
                    if (curIndex > 0)
                    {
                        curIndex -= 1;
                    }
                    curIndex -= end - start;

                    //复制替换数据
                    Buffer.BlockCopy(newValue, 0, newByteArray, curIndex, newValue.Length);
                    //计算新数组的偏移量
                    curIndex += newValue.Length;
                    //重新设置需要复制索引的索引
                    start = end = -1;
                }
            }

            //处理返回结果
            byte[] result = null;
            if (curIndex != 0)
            {
                result = new byte[curIndex];
                Buffer.BlockCopy(newByteArray, 0, result, 0, result.Length);
            }
            else
            {
                result = new byte[sourceByteArray.Length];
                Buffer.BlockCopy(sourceByteArray, 0, result, 0, result.Length);
            }
            return result;
        }

        /// <summary>
        /// 二进制替换,如果没有替换则返回原数组对像的复本.
        /// </summary>
        /// <param name="sourceByteArray">源数据</param>
        /// <param name="replaces">需要替换的数据集合</param>
        public static byte[] Replace(this byte[] sourceByteArray, List<HexReplaceEntity> replaces)
        {

            byte[] result = sourceByteArray;
            foreach (HexReplaceEntity rep in replaces)
            {
                result = result.Replace(rep.oldValue, rep.newValue);
            }
            return result;
        }
        /// <summary>
        /// 处理TCP协议数据协议
        /// 转换
        /// 0x67,->0x67 0x01 
        /// 0x68,->0x67 0x02
        ///0x16,->0x67 0x03 
        /// </summary>
        /// <param name="sourceByteArray">源数数据</param>
        /// <returns>返回处理对像的复本</returns>
        public static byte[] TcpReolacex68tox6702(this byte[] sourceByteArray)
        {
            List<byte> result = new List<byte>(sourceByteArray.Length);
            //替换数据替换
            for (int x = 0; x < sourceByteArray.Length; x++)
            {
                byte b = sourceByteArray[x];
                int n = x + 1;

                // 0x67,->0x67 0x01 
                if (b == 0x67)
                {
                    result.Add(0x67);
                    result.Add(0x01);
                    continue;
                }
                // 0x68,->0x67 0x02
                if (b == 0x68)
                {
                    result.Add(0x67);
                    result.Add(0x02);
                    continue;
                }
                //  0x16 ->0x67 0x03
                if (b == 0x16)
                {
                    result.Add(0x67);
                    result.Add(0x03);
                    continue;
                }

                result.Add(b);
            }

            byte[] resultArr = result.ToArray();
            result.Clear();
            result = null;
            return resultArr;
        }

        /// <summary>
        /// 处理TCP协议数据协议
        /// 还原
        /// 0x67 0x01 ->0x67,
        /// 0x67 0x02 ->0x68,
        /// 0x67 0x03 ->0x16
        /// </summary>
        /// <param name="sourceByteArray">源数数据</param>
        /// <returns>返回处理对像的复本</returns>
        public static byte[] TcpReolacex6702tox68(this byte[] sourceByteArray)
        {
            List<byte> result = new List<byte>(sourceByteArray.Length);
            //替换数据替换
            for (int x = 0; x < sourceByteArray.Length; x++)
            {
                byte b = sourceByteArray[x];
                int n = x + 1;
                //比较有效的数据
                if (sourceByteArray.Length > n)
                {
                    // 0x67 0x01 ->0x67,
                    if (b == 0x67 && sourceByteArray[n] == 0x01)
                    {
                        x += 1;
                        result.Add(0x67);
                        continue;
                    }
                    //0x67 0x02 ->0x68,
                    if (b == 0x67 && sourceByteArray[n] == 0x02)
                    {
                        x += 1;
                        result.Add(0x68);
                        continue;
                    }
                    //  0x67 0x03 ->0x16
                    if (b == 0x67 && sourceByteArray[n] == 0x03)
                    {
                        x += 1;
                        result.Add(0x16);
                        continue;
                    }
                }
                result.Add(b);
            }

            byte[] resultArr = result.ToArray();
            result.Clear();
            result = null;
            return resultArr;
        }


        /// <summary>
        /// 二进制替换,如果没有替换则返回原数组对像的复本. 内部使用List,比直接用数组替换效率低25%
        /// </summary>
        /// <param name="sourceByteArray">源数据</param>
        /// <param name="oldValue">需要替换的数据</param>
        /// <param name="newValue">将要替换成为的数据</param>
        public static byte[] ReplaceA(this byte[] sourceByteArray, byte[] oldValue, byte[] newValue)
        {
            //创建新数据多出1字节
            int newArrayLen = (int)((newValue.Length / (double)oldValue.Length) * sourceByteArray.Length) + 1;
            //得到数组长度
            newArrayLen = Math.Max(newArrayLen, sourceByteArray.Length);
            int oldCurindex = 0;
            List<byte> result = new List<byte>(newArrayLen);
            //替换数据替换
            for (int x = 0; x < sourceByteArray.Length; x++)
            {
                var b = sourceByteArray[x];
                result.Add(b);
                if (b == oldValue[oldCurindex])
                {
                    if (oldCurindex == oldValue.Length - 1)
                    {
                        oldCurindex = 0;
                        //称除现有数据
                        for (int k = 0; k < oldValue.Length; k++)
                        {
                            result.RemoveAt(result.Count - 1);
                        }
                        //添加新数据
                        result.AddRange(newValue);
                    }
                    else
                    {
                        oldCurindex++;
                    }
                }
            }
            byte[] resultarr = result.ToArray();
            result.Clear();
            result = null;
            return resultarr;

        }

    }

    /// <summary>
    /// 替换用的数据实体
    /// </summary>
    public class HexReplaceEntity
    {
        /// <summary>
        /// 需要替换的原始值
        /// </summary>
        public byte[] oldValue { get; set; }

        /// <summary>
        /// 新值
        /// </summary>
        public byte[] newValue { get; set; }

        ///// <summary>
        ///// 默认开始结束标记
        ///// </summary>
        //internal int start = -1;
        ///// <summary>
        ///// 默认开始结束标记
        ///// </summary>
        //internal int end = -1;

        ////当前查找到的索引
        //internal int oldCurindex = 0;

    }
}
